package com.stox.charting.ui.swing.model;

import java.util.ArrayList;
import java.util.List;

import com.stox.charting.ui.swing.event.ChartModelChangedEvent;
import com.stox.charting.ui.swing.event.listener.DataChangedEventListener;
import com.stox.charting.ui.swing.event.listener.ThemeChangedEventListener;
import com.stox.charting.ui.swing.event.listener.UiUnitsChangedEventListener;
import com.stox.charting.ui.swing.event.listener.ViewportChangedEventListener;
import com.stox.charting.ui.swing.scheme.color.ColorScheme;
import com.stox.ioc.Container;

public abstract class ChartModel<T> {

	public static interface ChartModelListener{
		public void chartModelChanged(ChartModelChangedEvent event);
	}

	private final List<ChartModelListener> chartModelListeners = new ArrayList<ChartModelListener>();
	protected final Chart<T> chart;
	protected List<T> data = new ArrayList<T>();
	protected ColorScheme<T> colorScheme;
	protected boolean eventsEnabled = true;
	
	public ChartModel(Chart<T> chart) {
		this.chart = chart;
		addChartModelListener(Container.get(DataChangedEventListener.class));
		addChartModelListener(Container.get(ThemeChangedEventListener.class));
		addChartModelListener(Container.get(UiUnitsChangedEventListener.class));
		addChartModelListener(Container.get(ViewportChangedEventListener.class));
	}
	
	public List<T> getData() {
		return data;
	}
	
	public void setData(List<T> data){
		boolean fireChartModelChangedEvent = 
						data != null && ((this.data != null && !this.data.equals(data)) || this.data == null);
		this.data = data;
		if(fireChartModelChangedEvent){
			fireChartModelChangedEvent("data");
		}
	}
	
	public abstract void constructUiUnits();
	
	public abstract Viewport<T> getViewport();
	
	public void fireChartModelChangedEvent(String property){
		if(eventsEnabled){
			ChartModelChangedEvent event = new ChartModelChangedEvent(property, this);
			for(ChartModelListener listener : chartModelListeners){
				listener.chartModelChanged(event);
			}
		}
	}
	
	public void addChartModelListener(ChartModelListener chartModelListener){
		chartModelListeners.add(chartModelListener);
	}
	
	public void removeChartModelListener(ChartModelListener chartModelListener){
		chartModelListeners.remove(chartModelListener);
	}

	public Chart<T> getChart() {
		return chart;
	}

	public ColorScheme<T> getColorScheme() {
		return colorScheme;
	}

	public void setColorScheme(ColorScheme<T> colorScheme) {
		
		boolean fireChartModelChangedEvent = 
				colorScheme != null && ((this.colorScheme != null && !this.colorScheme.equals(colorScheme)) || this.colorScheme == null);
		this.colorScheme = colorScheme;
		if(fireChartModelChangedEvent){
			fireChartModelChangedEvent("colorScheme");
		}
	}

	public boolean isEventsEnabled() {
		return eventsEnabled;
	}

	public void setEventsEnabled(boolean eventsEnabled) {
		this.eventsEnabled = eventsEnabled;
	}
}